package roles

import (
	"math/rand/v2"
	"time"

	"gitee.com/cjianwen/go/demo/socks_v2/raft_demo/server/consts"
	"gitee.com/cjianwen/go/demo/socks_v2/raft_demo/server/global"
	"gitee.com/cjianwen/go/logs"
	"gitee.com/cjianwen/go/utils"
)

type VoteInfos struct {
}

type condidate struct {
	*roleState

	beginVoteTime time.Time
	voteTimeout   uint32 // 随机超时时间
	isRequestVote bool
}

func (c *condidate) randomVoteTimout() {
	c.voteTimeout = consts.RequestVoteTimeout + uint32(rand.Float32()*consts.RandRequestVoteTimeout)
}

func (c *condidate) isVoteTimeout() bool {
	ret := utils.TimePassed(&c.beginVoteTime, c.voteTimeout)
	if ret {
		c.randomVoteTimout()
	}
	return ret
}

func (c *condidate) beginVote(term uint32) {
	c.beginVoteTime = time.Now()
	c.respVoteCount = 1
	c.myVoteCount = 1
	c.tryVoteTerm = term

	logs.Printf("BeginVote: currTerm = %d, timeout = %d", c.tryVoteTerm, c.voteTimeout)
}

func (c *condidate) Reset() {
	c.randomVoteTimout()
	c.isRequestVote = true
	c.beginVote(c.Term + 1)
	global.NodeConns.ConnSvrs()
}

func (c *condidate) Run() error {

	if c.myVoteCount > uint32(global.ServerInfo.ServerCountHalf) {
		logs.Printf("condidate.Run 投票满足，成为 leader, respCount = %d, voteCount = %d, tryTerm = %d, Term = %d", c.respVoteCount, c.myVoteCount, c.tryVoteTerm, c.Term)
		c.Term = c.tryVoteTerm
		c.becomeLeader()
		return nil
	}

	if global.NodeConns.ConnCountIsOK() { // 连接数正常就可以发起投票
		if c.isRequestVote {
			c.prot.RequestVote()
			c.isRequestVote = false
		}
	}

	if c.isVoteTimeout() {
		if global.NodeConns.ConnCountIsOK() {
			logs.Println("投票超时，再次发起投票")
			c.isRequestVote = true
			c.beginVote(c.tryVoteTerm + 1)
		} else {
			logs.Println("连接数不足，无法投票，当前连接数：", global.NodeConns.GetConnCount())
		}
	}
	return nil
}
